package com.ruoyi.workflow.service.impl;

import java.io.InputStream;
import java.rmi.ServerException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ruoyi.business.domain.ServiceItem;
import com.ruoyi.business.service.IServiceItemService;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.workflow.service.IBpmnNodeService;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.workflow.mapper.CarPackageAuditMapper;
import com.ruoyi.workflow.domain.CarPackageAudit;
import com.ruoyi.workflow.service.ICarPackageAuditService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 套餐审核Service业务层处理
 *
 * @author lhl
 * @date 2022-11-18
 */
@Service
public class CarPackageAuditServiceImpl extends ServiceImpl<CarPackageAuditMapper, CarPackageAudit> implements ICarPackageAuditService {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private IServiceItemService serviceItemService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private IBpmnNodeService nodeService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private DefaultProcessDiagramGenerator processDiagramGenerator;
    /**
     * 查询套餐审核列表
     *
     * @param carPackageAudit 套餐审核
     * @return 套餐审核
     */
    @Override
    public List<CarPackageAudit> selectCarPackageAuditList(CarPackageAudit carPackageAudit) {
        return getBaseMapper().selectCarPackageAuditList(carPackageAudit);
    }

    /*
    * 基于服务项目id更改服务项状态为审核中
    * 创建保存一条审核记录
    *
    *
    *
    * */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void startAudit(Long serviceItemId, String info) throws ServerException {
        //基于serviceItemId获取服务项对象
        ServiceItem serviceItem = serviceItemService.get(serviceItemId);
        //根据服务对象中的状态判断是否开启审核
        if (serviceItem.getAuditStatus()!=ServiceItem.AUDITSTATUS_INIT||serviceItem.getCarPackage()==ServiceItem.CARPACKAGE_NO){
            //无需审核抛出异常
            throw new ServerException("该记录不能开启审核,请检查是否为套餐或其状态");
        }
        //需要审核开启实例化将服务项对象中的状态更改--不是用set设置这里使用change方法
        serviceItemService.changeStatus(serviceItemId,ServiceItem.AUDITSTATUS_AUDITING);
        //创建审核对象存入审核记录表中
        CarPackageAudit carPackageAudit = new CarPackageAudit();
        carPackageAudit.setServiceItemId(serviceItemId);
        carPackageAudit.setServiceItemInfo(serviceItem.getInfo());
        carPackageAudit.setServiceItemName(serviceItem.getName());
        carPackageAudit.setServiceItemPrice(serviceItem.getDiscountPrice());
        carPackageAudit.setCreatorId(String.valueOf(SecurityUtils.getUserId()));
        carPackageAudit.setStatus(CarPackageAudit.AUDIT_STATUS_INPROGRESS);
        carPackageAudit.setInfo(info);
        //保存审核记录--之所以先保存审核记录是为了实例化流程是设置businessKey,其中businessKey为审核记录的id
        super.save(carPackageAudit);
        //开启实例(需要实例key,businessKey,map变量),其中businessKey=审核记录ID,map中存入流程中需要的数据例如:审核条件,审核候选人
        HashMap<String, Object> map = new HashMap<>();
        //存放变量
        map.put("money", serviceItem.getDiscountPrice().longValue());
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("bus_car_package", String.valueOf(carPackageAudit.getId()), map);
        //设置实例对象ID到审核记录中
        carPackageAudit.setInstanceId(instance.getId());
        //查询当前进行中的任务对象--基于流程实例ID获取
        Task task = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult();
       //基于任务key获取审核人  任务key=nodeKey
        List<SysUser> users=nodeService.selectUsersByNodeKey(task.getTaskDefinitionKey());
        System.out.println(task.getTaskDefinitionKey());
       //调用activiti的api为任务设置候选人
        for (SysUser user:users
             ) {
            taskService.addCandidateUser(task.getId(), user.getUserName());
        }
      //更新审核记录
        super.updateById(carPackageAudit);
    }

   /*
   *
   * 获取流程进度图
   *
   * */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public InputStream getProcessingImage(String instanceId) throws ServerException {

        //基于instanceId获取实例对象
        HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult();
        if (instance == null) {
            throw new ServerException("流程已结束");
        }
        // 根据流程实例对象获取流程定义id, service 查询 bpmnModel 对象
        BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
        //获取活动
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId).list();
        List<String> activities=list.stream().map(HistoricActivityInstance::getActivityId
        ).collect(Collectors.toList());

        return processDiagramGenerator.generateDiagram(bpmnModel, // 模型对象 == 流程文件转换的对象
                activities, // 需要高亮的活动 id 集合, 活动 == 所有运行的节点
                Collections.emptyList(), // 需要高亮的引导线 id 集合
                "宋体",
                "宋体",
                "宋体");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void revoke(Long id, String reason) throws ServerException {
        /*
         * 更改服务项中的状态为初始化--serviceItemService
         * 更改审核记录中的状态为审核状态--
         * 删除流程实例--runtimeService
         * */
        CarPackageAudit audit = getById(id);
        if (audit == null) {
            throw new ServerException("审核不存在");
        }
        if (audit.getStatus()!=CarPackageAudit.AUDIT_STATUS_INPROGRESS){
            throw new ServerException("该状态不允许撤销");
        }
        //更改服务项中的状态
        serviceItemService.changeStatus( audit.getServiceItemId(),ServiceItem.AUDITSTATUS_INIT);
        //更改审核记录中的状态
        audit.setStatus(CarPackageAudit.AUDIT_STATUS_REVOKE);
        updateById(audit);
        //删除流程实例
        runtimeService.deleteProcessInstance(audit.getInstanceId(),reason);
    }

    @Override
    public void updateAuditForm(Long auditId, ServiceItem serviceItem) {
        update(new LambdaUpdateWrapper<CarPackageAudit>()
                .set(CarPackageAudit::getServiceItemName,serviceItem.getName())
                .set(CarPackageAudit::getServiceItemInfo,serviceItem.getInfo())
                .set(CarPackageAudit::getServiceItemPrice,serviceItem.getDiscountPrice())
                .eq(CarPackageAudit::getId,auditId)
        );
    }

}
